﻿using System.Collections.Generic;

namespace TTUnityPlugin {
/// <summary>
/// A generic class for storing a pool of lists.
/// </summary>
/// <typeparam name="T">The list element type.</typeparam>
public static class LTListPool<T> {
    /// <summary>
    /// A disposable struct that can be used in conjunction with the "using" keyword to retrieve a pooled list.
    /// </summary>
    public struct Scope : System.IDisposable {
        #region Backing Fields
        private List<T> m_List;
        #endregion

        /// <summary>
        /// Gets the pooled hash set.
        /// </summary>
        /// <value>The pooled hash set.</value>
        public List<T> List { get { return m_List = m_List == null ? s_Pool.Get() : m_List; } }

        /// <summary>
        /// Releases all resource used by the <see cref="ListPool{T}.Scope"/> object.
        /// </summary>
        /// <remarks>
        /// Call <see cref="Dispose"/> when you are finished using the <see cref="ListPool{T}.Scope"/>. The
        /// <see cref="Dispose"/> method leaves the <see cref="ListPool{T}.Scope"/> in an unusable state. After
        /// calling <see cref="Dispose"/>, you must release all references to the <see cref="ListPool{T}.Scope"/>
        /// so the garbage collector can reclaim the memory that the <see cref="ListPool{T}.Scope"/> was
        /// occupying.
        /// </remarks>
        public void Dispose() {
            if(m_List != null) {
                s_Pool.Release(m_List);
            }
        }
    }

    /// <summary>
    /// An underlying <see cref="ObjectPool{T}"/>.
    /// </summary>
    private static readonly LTObjectPool<List<T>> s_Pool = new LTObjectPool<List<T>>(null, l => l.Clear());

    /// <summary>
    /// Gets an available list from the pool.
    /// </summary>
    /// <returns>An available list from the pool.</returns>
    public static List<T> Get() {
        return s_Pool.Get();
    }

    /// <summary>
    /// Releases a list to the pool.
    /// </summary>
    /// <param name="list">List to release.</param>
    public static void Release(List<T> list) {
        s_Pool.Release(list);
    }
}
}
